using System.Threading.Tasks;
using HslCommunication.BasicFramework;
using HslCommunication.Core;
using HslCommunication.Serial;

namespace HslCommunication.Profinet.Panasonic
{
	/// <summary>
	/// 松下PLC的数据交互协议，采用Mewtocol协议通讯，支持的地址列表参考api文档<br />
	/// The data exchange protocol of Panasonic PLC adopts Mewtocol protocol for communication. For the list of supported addresses, refer to the api document.
	/// </summary>
	/// <remarks>
	/// <inheritdoc cref="T:HslCommunication.Profinet.Panasonic.PanasonicMewtocolOverTcp" path="remarks" />
	/// </remarks>
	public class PanasonicMewtocol : SerialDeviceBase
	{
		/// <inheritdoc cref="P:HslCommunication.Profinet.Panasonic.PanasonicMewtocolOverTcp.Station" />
		public byte Station
		{
			get;
			set;
		}

		/// <inheritdoc cref="M:HslCommunication.Profinet.Panasonic.PanasonicMewtocolOverTcp.#ctor(System.Byte)" />
		public PanasonicMewtocol(byte station = 238)
		{
			base.ByteTransform = new RegularByteTransform();
			Station = station;
			base.ByteTransform.DataFormat = DataFormat.DCBA;
		}

		/// <inheritdoc cref="M:HslCommunication.Profinet.Panasonic.PanasonicMewtocolOverTcp.Read(System.String,System.UInt16)" />
		public override OperateResult<byte[]> Read(string address, ushort length)
		{
			OperateResult<byte[]> operateResult = PanasonicHelper.BuildReadCommand(Station, address, length);
			if (!operateResult.IsSuccess)
			{
				return operateResult;
			}
			OperateResult<byte[]> operateResult2 = ReadBase(operateResult.Content);
			if (!operateResult2.IsSuccess)
			{
				return operateResult2;
			}
			return PanasonicHelper.ExtraActualData(operateResult2.Content);
		}

		/// <inheritdoc cref="M:HslCommunication.Profinet.Panasonic.PanasonicMewtocolOverTcp.Write(System.String,System.Byte[])" />
		public override OperateResult Write(string address, byte[] value)
		{
			OperateResult<byte[]> operateResult = PanasonicHelper.BuildWriteCommand(Station, address, value, -1);
			if (!operateResult.IsSuccess)
			{
				return operateResult;
			}
			OperateResult<byte[]> operateResult2 = ReadBase(operateResult.Content);
			if (!operateResult2.IsSuccess)
			{
				return operateResult2;
			}
			return PanasonicHelper.ExtraActualData(operateResult2.Content);
		}

		/// <inheritdoc cref="M:HslCommunication.Profinet.Panasonic.PanasonicMewtocolOverTcp.ReadBool(System.String,System.UInt16)" />
		public override OperateResult<bool[]> ReadBool(string address, ushort length)
		{
			OperateResult<byte[]> operateResult = Read(address, (ushort)(((int)length % 16 == 0) ? ((int)length / 16) : ((int)length / 16 + 1)));
			if (!operateResult.IsSuccess)
			{
				return OperateResult.CreateFailedResult<bool[]>(operateResult);
			}
			byte[] inBytes = SoftBasic.BytesReverseByWord(operateResult.Content);
			return OperateResult.CreateSuccessResult(SoftBasic.ByteToBoolArray(inBytes, length));
		}

		/// <inheritdoc cref="M:HslCommunication.Profinet.Panasonic.PanasonicMewtocolOverTcp.ReadBool(System.String)" />
		public override OperateResult<bool> ReadBool(string address)
		{
			OperateResult<byte[]> operateResult = PanasonicHelper.BuildReadOneCoil(Station, address);
			if (!operateResult.IsSuccess)
			{
				return OperateResult.CreateFailedResult<bool>(operateResult);
			}
			OperateResult<byte[]> operateResult2 = ReadBase(operateResult.Content);
			if (!operateResult2.IsSuccess)
			{
				return OperateResult.CreateFailedResult<bool>(operateResult2);
			}
			return PanasonicHelper.ExtraActualBool(operateResult2.Content);
		}

		/// <inheritdoc cref="M:HslCommunication.Profinet.Panasonic.PanasonicMewtocolOverTcp.Write(System.String,System.Boolean[])" />
		public override OperateResult Write(string address, bool[] values)
		{
			byte[] inBytes = SoftBasic.BoolArrayToByte(values);
			OperateResult<byte[]> operateResult = PanasonicHelper.BuildWriteCommand(Station, address, SoftBasic.BytesReverseByWord(inBytes), (short)values.Length);
			if (!operateResult.IsSuccess)
			{
				return operateResult;
			}
			OperateResult<byte[]> operateResult2 = ReadBase(operateResult.Content);
			if (!operateResult2.IsSuccess)
			{
				return operateResult2;
			}
			return PanasonicHelper.ExtraActualData(operateResult2.Content);
		}

		/// <inheritdoc cref="M:HslCommunication.Profinet.Panasonic.PanasonicMewtocolOverTcp.Write(System.String,System.Boolean)" />
		public override OperateResult Write(string address, bool value)
		{
			OperateResult<byte[]> operateResult = PanasonicHelper.BuildWriteOneCoil(Station, address, value);
			if (!operateResult.IsSuccess)
			{
				return operateResult;
			}
			OperateResult<byte[]> operateResult2 = ReadBase(operateResult.Content);
			if (!operateResult2.IsSuccess)
			{
				return operateResult2;
			}
			return PanasonicHelper.ExtraActualData(operateResult2.Content);
		}

		/// <inheritdoc cref="M:HslCommunication.Profinet.Panasonic.PanasonicMewtocol.ReadBool(System.String)" />
		public override async Task<OperateResult<bool>> ReadBoolAsync(string address)
		{
			return await Task.Run(() => ReadBool(address));
		}

		/// <inheritdoc cref="M:HslCommunication.Profinet.Panasonic.PanasonicMewtocol.Write(System.String,System.Boolean)" />
		public override async Task<OperateResult> WriteAsync(string address, bool value)
		{
			return await Task.Run(() => Write(address, value));
		}

		/// <inheritdoc />
		public override string ToString()
		{
			return $"Panasonic Mewtocol[{base.PortName}:{base.BaudRate}]";
		}
	}
}
